<template>
  <div class="page-wrapper">
    <!-- 对话内容区域 -->
    <div class="chat-messages" ref="messagesWrap">
      <div 
        v-for="(msg, idx) in messages" 
        :key="msg.id"
        class="message-group"
        @mouseenter="hoveredMessage = msg.id"
        @mouseleave="hoveredMessage = null"
      >
        <!-- 用户消息 -->
        <template v-if="msg.type === 'user'">
          <!-- 图片气泡 -->
          <div
            v-if="msg.images && msg.images.length > 0"
            class="chat-message user-message image-bubble"
          >
            <div class="message-content">
              <div class="adaptive-image-container" ref="imageContainers[idx]">
                <img
                  v-for="(img, i) in msg.images"
                  :key="i"
                  :src="img.url"
                  alt="用户上传的图片"
                  class="adaptive-chat-img"
                  @click="showMessageImage(img, idx, i)"
                  @load="calculateImageSize(img, $event, idx, i)"
                  :style="{
                    '--aspect-ratio': imageSizes[`${idx}-${i}`]?.aspectRatio || '1/1',
                    'max-width': '100%'
                  }"
                />
              </div>
            </div>
          </div>
          
          <!-- 文本气泡 -->
          <div
            v-if="msg.textContent"
            class="chat-message user-message"
          >
            <div class="message-content">
              <p class="text">{{ msg.textContent }}</p>
            </div>
            <div 
              class="message-actions user-actions"
              v-show="hoveredMessage === msg.id"
            >
  
            <el-tooltip content="修改" placement="top">
                  <div 
                      class="action-btn edit-btn" 
                        @click="editTextMessage(msg)"
                           :class="{ 'disabled-btn': isGenerating }" 
                        :title="isGenerating? '生成中...' : '修改'" >
                        <el-icon><Edit /></el-icon>
                   </div>
             </el-tooltip>

              <el-tooltip content="复制" placement="top">
                <div class="action-btn copy-btn" @click="copyText(msg.textContent)">
                  <el-icon><DocumentCopy /></el-icon>
                </div>
              </el-tooltip>
            </div>
          </div>
        </template>

           <!-- ai文本气泡 -->
      <div v-if="msg.type === 'ai'" class="ai-message-group">

  <div 
    v-if=" (msg.thoughtContent || msg.isThinking)"
    class="chat-message ai-message thought-message"
    @mouseenter="hoveredMessage = msg.id"
    @mouseleave="hoveredMessage = null"
  >
    <div class="message-content">
      <!-- 思考动画 -->
      <p class="text" v-if="msg.isThinking">
        <span class="dot-pulse">
          <span>.</span><span>.</span><span>.</span>
        </span>
      </p>
      <!-- 思考内容 -->
       <div v-else>
      <div class="thought-header" @click="toggleThoughtFold(msg.id)">
        <h1 class="thought-title">推理过程</h1>
        <el-icon class="fold-icon">
          <ArrowUp v-if="!msg.isFolded" />
          <ArrowDown v-else />
        </el-icon>
      </div>
      <div class="thought-content" v-html="processContent(msg.thoughtContent)" v-show="!msg.isFolded"></div>

  </div>
     
    </div>
  </div>

  <!-- 答案气泡 - 进入答案阶段后显示 -->
  <div 
    v-if="msg.answerStarted && msg.content"
    class="chat-message ai-message answer-message"
   
  >
    <div class="message-content">
      <div class="text" v-html="processContent(msg.content)"></div>
    </div>
    <div class="message-actions ai-actions">
      <el-tooltip content="复制" placement="top">
        <div class="action-btn copy-btn" @click="copyText(msg.content)">
          <el-icon><DocumentCopy /></el-icon>
        </div>
      </el-tooltip>
      <el-tooltip :content="isGenerating? '生成中...' : '重新生成'" placement="top">
        <div 
          class="action-btn regenerate-btn" 
          @click="!isGenerating && regenerateResponse(msg.id)"
          :class="{ 'disabled-btn': isGenerating }"
        >
          <el-icon><Refresh /></el-icon>
        </div>
      </el-tooltip>
    </div>
  </div>

  <!-- 工具气泡 - 最后单独显示 -->
  <div 
    v-if="msg.showTool && msg.toolContent"
    class="chat-message ai-message tool-message"
    @mouseenter="hoveredMessage = msg.id"
    @mouseleave="hoveredMessage = null"
  >
    <div class="message-content">
      <div class="tool-content" v-html="msg.toolContent"></div>
    </div>
    <div class="message-actions ai-actions" v-show="hoveredMessage === msg.id">
      <el-tooltip content="复制" placement="top">
        <div class="action-btn copy-btn" @click="copyText(msg.toolContent)">
          <el-icon><DocumentCopy /></el-icon>
        </div>
      </el-tooltip>
    </div>
  </div>
</div>
  
      </div>
    </div>

    <!-- 底部固定区域 -->
    <div class="fixed-bottom">
      <div class="files-info">
        <div 
          v-for="(file, index) in selectedFiles" 
          :key="file.id" 
          class="file-item"
        >
          <div class="file-tag" @click="showPreviewFile(file)">
            <span class="file-name">{{ truncateFileName(file.name) }}</span>
            <span class="file-size"> ({{ formatFileSize(file.size) }})</span>
             <span class="close-icon" @click.stop="removeFile(index)">×</span>
          </div>
        </div>
      </div>



      <div class="input-area">
        <el-input
          v-model="textarea2"
          class="custom-textarea"
          type="textarea"
          placeholder="请输入要查询的信息"
          @keydown.enter.prevent="handleEnter"  
          @keydown.ctrl.enter="insertNewLine"  
          :autosize="{ minRows: 3, maxRows: 10 }"
          resize="none"
          :disabled="isGenerating"
        />
      <div class="buttons-left" >
        <div 
          class="rect-button"
        
          @click="handleSingleChar"
      
        >
          <span>已识甲骨文字识别</span>
        </div>
        <div 
          class="rect-button"
         
          @click="handleCharSearch"
         
        >
          <span>甲骨文字检索</span>
        </div>
        <div 
          class="rect-button"
         
          @click="handleRubbingGen"
         
        >
          <span>拓片摹本生成</span>
        </div>
               <div 
          class="rect-button"
         
          @click="handleRubbingSearch"
         
        >
          <span>拓片重见检索</span>
        </div>
      </div>

        <div class="buttons">
          <div 
            class="circle2" 
            @click="openFileDialog" 
            title="点击上传图片（可多选）"
            :class="{ disabled: isGenerating }"
          >
            <el-icon class="icron3"><Link /></el-icon>
            <input
              ref="fileInput"
              type="file"
              style="display: none"
              accept="image/*"
              multiple
              @change="handleFileUpload"
            />
          </div>
          <!-- 发送/停止按钮（核心） -->
          <div
            class="circle"
            :class="{
             'has-content': (textarea2 || '').trim()!== '' || selectedFiles.length > 0,
              'stop-btn': isGenerating,
               'disabled': (!textarea2.trim() && selectedFiles.length === 0) && isGenerating === false
            }"
            @click="isGenerating? stopGenerating(sessionId) : handleQuestion()"
          >
            <el-icon class="icon2" :size="20">
              <Top v-if="!isGenerating" />
              <Close v-if="isGenerating" />
            </el-icon>
          </div>
        </div>
      </div>
    </div>

    <!-- 图片预览对话框 -->
    <el-dialog 
      v-model="dialogVisible" 
      title="图片预览" 
      width="60%"
      @closed="resetPreview"
    >
      <div 
        class="preview-container"
        :class="{ 'grabbing': isDragging }"
        @wheel.prevent="handleZoom"
        @mousedown.prevent="startDrag"
        @mousemove.prevent="onDrag"
        @mouseup.prevent="endDrag"
        @mouseleave.prevent="endDrag"
      >
        <img 
          ref="previewImgEl"
          :src="previewImgData.url" 
          :style="imgTransform"
          class="preview-content"
          draggable="false"
          @dragstart.prevent
        />
      </div>
      <template #footer>
        <div class="preview-controls">
          <el-button @click="zoomIn" circle size="small">
            <el-icon><Plus /></el-icon>
          </el-button>
          <el-button @click="zoomOut" circle size="small">
            <el-icon><Minus /></el-icon>
          </el-button>
          <el-button @click="resetPreview" circle size="small">
            <el-icon><Refresh /></el-icon>
          </el-button>
          <el-button @click="downloadImage" circle size="small">
            <el-icon><Download /></el-icon>
          </el-button>
          <span class="zoom-info">缩放: {{ (zoomLevel * 100).toFixed(0) }}%</span>
        </div>
      </template>
    </el-dialog>
  </div>
</template>

<script setup>
import MarkdownIt from'markdown-it'
import { useRouter } from 'vue-router'
import { useUserStore } from '@/stores'
import { ref, nextTick, computed, watch, onMounted, onUnmounted,onBeforeUnmount,  reactive } from 'vue'
import { Top, Link, DocumentCopy, Refresh, Close, Plus, Minus, Edit, Download } from '@element-plus/icons-vue'
import { ElMessage, ElDialog, ElInput, ElTooltip, ElButton, ElSwitch } from 'element-plus'
import { historicalrecor  } from '@/api/Historical_record_question'
import { historicaldialogue } from '@/api/Historical_dialogue'
import { useQuestionStore } from '@/stores'
import { onBeforeRouteLeave } from 'vue-router'
import fileData from '@/assets/name2path.json'
const userStore = useUserStore()



const handleBeforeUnload = (event) => {
  // 在这里执行你的清理逻辑
  userquestion.isGenerating = false;
  userquestion.isNew = false;
  
};

onMounted(() => {
  // 添加事件监听
  window.addEventListener('beforeunload', handleBeforeUnload);
});

onBeforeUnmount(() => {
  // 移除事件监听
  window.removeEventListener('beforeunload', handleBeforeUnload);
  
  // 组件卸载时也执行同样的逻辑
  userquestion.isGenerating = false;
  userquestion.isNew = false;
});

// 如果你使用的是 Vue Router，还可以添加路由离开的守卫
onBeforeRouteLeave(() => {
  userquestion.isGenerating = false;
  userquestion.isNew = false;
});



const md = new MarkdownIt();
md.renderer.rules.link_open = function (tokens, idx, options, env, self) {
  const token = tokens[idx];
  
  // 添加 target="_blank"（如果不存在）
  const targetIndex = token.attrIndex('target');
  if (targetIndex < 0) {
    token.attrPush(['target', '_blank']);
  } else {
    token.attrs[targetIndex][1] = '_blank';
  }

  // 添加 rel="noopener noreferrer"（如果不存在）
  const relIndex = token.attrIndex('rel');
  if (relIndex < 0) {
    token.attrPush(['rel', 'noopener noreferrer']);
  } else {
    token.attrs[relIndex][1] = 'noopener noreferrer';
  }

  // 调用默认的渲染逻辑
  return self.renderToken(tokens, idx, options);
};

// 自定义图片渲染规则，添加点击放大功能
md.renderer.rules.image = function (tokens, idx, options, env, self) {
  const token = tokens[idx];
  const srcIndex = token.attrIndex('src');
  const altIndex = token.attrIndex('alt');
  
  if (srcIndex < 0) {
    return self.renderToken(tokens, idx, options);
  }
  
  const src = token.attrs[srcIndex][1];
  const alt = altIndex >= 0 ? token.attrs[altIndex][1] : '';
  
  // 添加点击事件，调用图片预览功能
  return `<img src="${src}" alt="${alt}" style="cursor: pointer; max-width: 100%;" onclick="window.previewMarkdownImage('${src}')" />`;
};


// 在处理消息时转换Markdown
const processContent = (content) => {
  return md.render(content || '');
};

// Markdown图片预览方法
const previewMarkdownImage = (src) => {
  previewImgData.value = {
    url: src,
    name: 'Markdown图片'
  };
  dialogVisible.value = true;
};

// 将方法挂载到window对象上，以便在markdown渲染中调用
if (typeof window !== 'undefined') {
  window.previewMarkdownImage = previewMarkdownImage;
}
const userquestion = useQuestionStore()
const fileInput = ref(null)
const textarea2 = ref('')  
const selectedFiles = ref([])
const hoveredMessage = ref(null)
let fileIdCounter = 0


// 添加折叠/展开方法
const toggleThoughtFold = (msgId) => {
  const msg = messages.value.find(m => m.id === msgId)
  if (msg) {
    msg.isFolded = !msg.isFolded
  }
}

const fetchSessionHistory = async (sessionId) => {
  // console.log('我执行了哦')
  try {
    const response = await historicaldialogue(sessionId);
    
    messages.value = response.map((record, index) => {
      const isUserMessage = record.role === 'user';
      const baseMessage = {
        id: record.created_at || `hist-${index}-${Date.now()}`,
        type: isUserMessage ? 'user' : 'ai',
        timestamp: record.created_at ? new Date(record.created_at).getTime() : Date.now(),
      };

      if (isUserMessage) {
        const images = [];
        if (record.image_url) {
          // 处理base64图片或普通URL
          const imageUrl = record.image_url.startsWith('data:') 
            ? record.image_url 
            : `data:image/png;base64,${record.image_url}`;
          images.push({
            url: imageUrl,
            name: '用户上传图片',
            id: `img-${index}-${Date.now()}`
          });
        }
        return {
          ...baseMessage,
          textContent: record.content || '',
          images
        };
      } else {
        return {
          ...baseMessage,
          thoughtContent: processMessage(record.reasoning) || '',
          content: processMessage(record.content) || '',
          answerStarted:'true',
          showTool:'true',

          
          // 补充AI回复可能的附加信息字段
          //  toolContent: record.tool_message || null
        };
      }
    });


    isGenerating.value = false;
      userquestion.isGenerating=false;
    await nextTick();
    scrollToBottom();
  } catch (err) {
    console.error('加载历史记录失败:', err);
    ElMessage.error(`加载历史记录失败: ${err.message || '未知错误'}`);
  }
};
// 核心状态变量：控制AI生成状态
const isGenerating = ref(false) // 是否正在生成回复

const currentAIMessageId = ref(null) // 当前AI消息ID

// 统一存储所有消息
const messages = ref([])
const imageSizes = ref({})
const imageContainers = ref({})
const messagesWrap = ref(null)


function generateUUID() {
  return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) {
    const r = Math.random() * 16 | 0;
    const v = c === 'x' ? r : (r & 0x3 | 0x8);
    return v.toString(16);
  });
}



   const sessionId = ref(null)
 onMounted(async () => {
   const filename = "kkubxqkxrsxvjcaxagbvloppidaa.jpg";
   const nFolders = 100; // 必须是100
   // console.log('111---');
  console.log(getTargetFolderSync(filename, nFolders));
   // 生成对话id
    if (userStore.sessionId) {
        sessionId.value  = userStore.sessionId ;
        console.log(userStore.sessionId)
         userquestion.setQuestionSessionId(sessionId.value)
         fetchSessionHistory(sessionId.value)
         return
   }
  // 从store恢复数据到表单
  textarea2.value = userquestion.currentQuestion || ''
  console.log(textarea2.value)
  selectedFiles.value = [...userquestion.selectedFiles] // 深拷贝
  console.log(selectedFiles.value)
  // 如果有内容则自动提交
  if (textarea2.value.trim() || selectedFiles.value.length > 0) {
    sessionId.value  = generateUUID();
    console.log('generateUUID生成的uuid是', sessionId.value )
    if (userquestion.isNew) {
      userStore.chatHistory.unshift({
        sessionId: sessionId.value,
        title: '新对话',
      })
      userStore.updatesessionId(sessionId.value)
    }

    userquestion.setQuestionSessionId(sessionId.value)
    await nextTick() // 等待DOM更新
    handleQuestion() // 执行提交
    // 提交后清空store
    userquestion.setSelectedFiles([])
    userquestion.setCurrentQuestion('')
    return
  }

  fetchSessionHistory(userquestion.questionsessionid)
  sessionId.value = userquestion.questionsessionid
  userStore.updatesessionId(sessionId.value)

  // 滚动到底部
  await scrollToBottom()
})
import CryptoJS from 'crypto-js';
function getTargetFolderSync(fileNameStr, nFolders, folderNames) {
  // 使用 CryptoJS.SHA256 进行同步哈希计算
  const hashHex = CryptoJS.SHA256(fileNameStr).toString(CryptoJS.enc.Hex);
 
  const hashInt = BigInt('0x' + hashHex);
  const folderIndex = Number(hashInt % BigInt(nFolders));
  
  if (folderNames) {
    return folderNames[folderIndex];
  }
  
  return `${(folderIndex + 1).toString().padStart(4, '0')}`;
}
const tagObjectDetectionCropRegex = /<tag_object_detection_crop>(.*?)<\/tag_object_detection_crop>/g;
const tagCompleteFasicalRegex = /<tag_complete_fasical>(.*?)<\/tag_complete_fasical>/g;
const tagSingleFasicalRegex = /<tag_single_fasical>(.*?)<\/tag_single_fasical>/g;
const tagDocumentHashNameRegex = /<tag_document_hash_name>(.*?)<\/tag_document_hash_name>/g;
const tagFontMatchHashNameRegex = /<tag_font_match_hash_name>(.*?)<\/tag_font_match_hash_name>/g;
const tagAllFontMatchHashNameRegex = /<tag_all_font_match_hash_name>(.*?)<\/tag_all_font_match_hash_name>/g;
const tagRubbingNameRegex = /<tag_rubbing_name>(.*?)<\/tag_rubbing_name>/g;
const tag_user_input = /<tag_user_input>(.*?)<\/tag_user_input>/g;
const tag_object_table = /<tag_object_table>(.*?)<\/tag_object_table>/g;
const tag_font_match = /<tag_font_match>(.*?)<\/tag_font_match>/g;
const tag_document = /<tag_document>(.*?)<\/tag_document>/g;
// 替换函数，将标签内容转为超链接
function parseDocPath(docName, fileData) {
  
  const fileName = docName.split('.').shift()
  // console.log('docName',fileName);
  if (!fileData[fileName]) {
    // throw new Error(`未找到文档: ${docName}`);
  }
  const fullPath = fileData[fileName];
  // console.log('fullPath',fullPath);
  
  // 验证文件名是否以.pdf结尾
  // if (!fileName.endsWith('.pdf')) {
  //   // throw new Error(`文件格式不支持: ${fileName}`);
  // }
  
  return fullPath

}
function processMessage(message) {
   if (tag_document.test(message)) {
  // 重置正则表达式状态（因为test()会改变lastIndex）
    tag_document.lastIndex = 0;
    // 替换标签为超链接
     
    message= message.replace(tag_document, (match, respone) => {
      const path = parseDocPath(respone,fileData)
      console.log(path);
      
      // 这里假设你的超链接格式，根据实际需求修改
      return `[${respone.split('.').shift()}](${rang(path)})`;
    });
  }
  // 检查是否包含目标标签
    if (tag_font_match.test(message)) {
  // 重置正则表达式状态（因为test()会改变lastIndex）
    tag_font_match.lastIndex = 0;
    
    // 替换标签为超链接
    message= message.replace(tag_font_match, (match, content) => {
      // 这里假设你的超链接格式，根据实际需求修改
      // console.log('content',Inscriptions(content));
      console.log('tag_font_match',Inscriptions(content));
      return `[${content}](${Inscriptions(content)})`;
    });
  }
  if (tagObjectDetectionCropRegex.test(message)) {
  // 重置正则表达式状态（因为test()会改变lastIndex）
    tagObjectDetectionCropRegex.lastIndex = 0;
    
    // 替换标签为超链接
    message= message.replace(tagObjectDetectionCropRegex, (match, content) => {
      console.log('tagObjectDetectionCropRegex',href(content));
      // 这里假设你的超链接格式，根据实际需求修改
      return `![${content}](${href(content)})`;
    });
  }
  if (tagCompleteFasicalRegex.test(message)) {
  tagCompleteFasicalRegex.lastIndex = 0;
   message= message.replace(tagCompleteFasicalRegex, (match, content) => {
    console.log('tagCompleteFasicalRegex',href(content));
      // 这里假设你的超链接格式，根据实际需求修改
      return `![${content}](${href(content)})`;
    });
  }
  if (tagSingleFasicalRegex.test(message)) {
  tagSingleFasicalRegex.lastIndex = 0;
   message= message.replace(tagSingleFasicalRegex, (match, content) => {
    console.log('SingleFasica',href(content));
      // 这里假设你的超链接格式，根据实际需求修改
      return `![${content}](${href(content)})`;
    });
  }
  if(tagDocumentHashNameRegex.test(message)){
    tagDocumentHashNameRegex.lastIndex = 0;
    message= message.replace(tagDocumentHashNameRegex, (match, content) => {
      // 这里假设你的超链接格式，根据实际需求修改
      console.log('hashHref',hashHref(content));
      return `![${content}](${hashHref(content)})`;
    });
  }
  if(tagFontMatchHashNameRegex.test(message)){
    tagFontMatchHashNameRegex.lastIndex = 0;
    message= message.replace(tagFontMatchHashNameRegex, (match, content) => {
      // 这里假设你的超链接格式，根据实际需求修改
      console.log('FontMatchHash',hashHref(content));
      return `![${content}](${hashHref(content)})`;
    });
  }
  if(tagAllFontMatchHashNameRegex.test(message)){
    tagAllFontMatchHashNameRegex.lastIndex = 0;
    message= message.replace(tagAllFontMatchHashNameRegex,(match, content) => {
      // 这里假设你的超链接格式，根据实际需求修改
      console.log('AllFontMatchHash',hashHref(content));
      return `![${content}](${hashHref(content)})`;
    });
  }
  if(tagRubbingNameRegex.test(message)){
    tagRubbingNameRegex.lastIndex = 0;
    message= message.replace(tagRubbingNameRegex, (match, content) => {
      // 这里假设你的超链接格式，根据实际需求修改
      console.log('rubbingHref',rubbingHref(content));
      return `[${content}](${rubbingHref(content)})`;
    });
  }
  if(tag_user_input.test(message)){
    tag_user_input.lastIndex = 0;
    message= message.replace(tag_user_input, (match, content) => {
      return `[${content}](${content})`;
    });
  }
  if(tag_object_table.test(message)){
    tag_object_table.lastIndex = 0;
    message= message.replace(tag_object_table, (match, content) => {
      return `[${content}](${content.split(',')[0]})`;
    });
  }
  return message; // 如果不包含标签，返回原消息
}
const rang = (content)=>{
  return  `https://static.jgw.qq.com/oracledoc/${content}`
}
const rubbingHref = (content)=>{
  return `https://jgw.aynu.edu.cn/home/zl/search/index.html?value=${content.replace(/,/g, '')}&query=2&key=PM&nav=1&type=0`
}

const hashHref =  (content)=>{
    const folderName = getTargetFolderSync(content, 100);
    return `https://aigc-static.jgw.qq.com/${folderName}/${content}`
}

const href = (content)=>{
  return `https://ms-p89j4ssn-100022641385.gw.ap-guangzhou.ti.tencentcs.com/ms-p89j4ssn/images/${content}`
}
const Inscriptions = (content) => {
  return `https://test.jgwlbq.org.cn/oracle-font/detail?code=${content}`
}
watch(
  () => userStore.sessionId,
  async (newVal, oldVal) => {
    if (newVal=='') {
      return
    }
    if (newVal==''&&isGenerating.value) {
      await stopGenerating()
      return
     }

     if (useQuestionStore().isNew) {
      return
    }
    sessionId.value=newVal;
    userquestion.setQuestionSessionId(sessionId.value)
    await nextTick() // 等待DOM更新
    handleQuestion() // 执行提交
    // 提交后清空store
    // userquestion.setSelectedFiles([])
    // userquestion.setCurrentQuestion('')
    console.log("userquestion.questionsessionid",userquestion.questionsessionid)
    console.log("usertore",)
    fetchSessionHistory(sessionId.value)
  }
);
watch(
  () => userquestion.isNew,
  async (newVal, oldVal) => {
    if (!newVal) {
      const res = await historicalrecor(); 
      userStore.addChatMessage(res);
    }
  }
)

// 图片预览相关
const dialogVisible = ref(false)
const previewImgData = ref({ url: '', name: '' })
const previewImgEl = ref(null)
const zoomLevel = ref(1)
const isDragging = ref(false)
const imgPosition = ref({ x: 0, y: 0 })
const dragStartPos = ref({ x: 0, y: 0 })
const dragStartOffset = ref({ x: 0, y: 0 })
const baseUrl = import.meta.env.VITE_BASE_URL

const imgTransform = computed(() => ({
  transform: `translate(${imgPosition.value.x}px, ${imgPosition.value.y}px) scale(${zoomLevel.value})`,
  cursor: isDragging.value ? 'grabbing' : (zoomLevel.value > 1 ? 'grab' : 'default')
}))



const handleZoom = (e) => {
  e.preventDefault()
  const delta = e.deltaY > 0 ? -0.1 : 0.1
  const newZoom = Math.min(Math.max(0.1, zoomLevel.value + delta), 5)
  
  // 保持当前位置不变，只更新缩放比例
  zoomLevel.value = newZoom
  
  // 如果图片小于容器，强制居中
  const container = e.currentTarget.getBoundingClientRect()
  const imgWidth = previewImgEl.value.naturalWidth * zoomLevel.value
  const imgHeight = previewImgEl.value.naturalHeight * zoomLevel.value
  
  if (imgWidth <= container.width && imgHeight <= container.height) {
    imgPosition.value = { x: 0, y: 0 }
  }
}

const zoomIn = () => {
  const newZoom = Math.min(zoomLevel.value + 0.1, 5)
  zoomLevel.value = newZoom
  
  const container = previewImgEl.value?.parentElement.getBoundingClientRect()
  if (!container) return
  
  const imgWidth = previewImgEl.value.naturalWidth * zoomLevel.value
  const imgHeight = previewImgEl.value.naturalHeight * zoomLevel.value
  
  if (imgWidth <= container.width && imgHeight <= container.height) {
    imgPosition.value = { x: 0, y: 0 }
  }
}

const zoomOut = () => {
  const newZoom = Math.max(zoomLevel.value - 0.1, 0.1)
  zoomLevel.value = newZoom
  
  const container = previewImgEl.value?.parentElement.getBoundingClientRect()
  if (!container) return
  
  const imgWidth = previewImgEl.value.naturalWidth * zoomLevel.value
  const imgHeight = previewImgEl.value.naturalHeight * zoomLevel.value
  
  if (imgWidth <= container.width && imgHeight <= container.height) {
    imgPosition.value = { x: 0, y: 0 }
  }
}




const startDrag = (e) => {
  if (zoomLevel.value <= 1) return
  
  isDragging.value = true
  dragStartPos.value = {
    x: e.clientX,
    y: e.clientY
  }
  dragStartOffset.value = {
    x: imgPosition.value.x,
    y: imgPosition.value.y
  }
  document.body.style.userSelect = 'none'
  document.body.style.cursor = 'grabbing'
}

const onDrag = (e) => {
  if (!isDragging.value || zoomLevel.value <= 1) return
  
  const dx = e.clientX - dragStartPos.value.x
  const dy = e.clientY - dragStartPos.value.y
  
  imgPosition.value = {
    x: dragStartOffset.value.x + dx,
    y: dragStartOffset.value.y + dy
  }
  
  const container = previewImgEl.value?.parentElement.getBoundingClientRect()
  if (!container) return
  
  const imgWidth = previewImgEl.value.naturalWidth * zoomLevel.value
  const imgHeight = previewImgEl.value.naturalHeight * zoomLevel.value
  
  // 限制移动范围
  if (imgWidth > container.width) {
    const maxX = (imgWidth - container.width) / 2
    const minX = -maxX
    imgPosition.value.x = Math.max(minX, Math.min(maxX, imgPosition.value.x))
  } else {
    imgPosition.value.x = 0
  }
  
  if (imgHeight > container.height) {
    const maxY = (imgHeight - container.height) / 2
    const minY = -maxY
    imgPosition.value.y = Math.max(minY, Math.min(maxY, imgPosition.value.y))
  } else {
    imgPosition.value.y = 0
  }
}

const endDrag = () => {
  isDragging.value = false
  document.body.style.userSelect = ''
  document.body.style.cursor = ''
}



const resetPreview = () => {
  zoomLevel.value = 1
  imgPosition.value = { x: 0, y: 0 }
}

const showPreviewFile = (item) => {
  previewImgData.value = {
    url: item.url,
    name: item.name
  }
  dialogVisible.value = true
}

const showMessageImage = (img, msgIndex, imgIndex) => {
  previewImgData.value = {
    url: messages.value[msgIndex].images[imgIndex].url,
    name: messages.value[msgIndex].images[imgIndex].name
  }
  dialogVisible.value = true
} 

// 编辑文本消息（覆盖输入框内容）
const editTextMessage = (msg) => {
  if (isGenerating.value) return;  // AI思考中直接返回（双重保险）
  
  // 覆盖输入框内容（清空原有内容）
  textarea2.value = msg.textContent || '';
  
  // 清空已选文件（避免混合内容干扰）
  selectedFiles.value = [];
  
};

// 复制文本
const copyText = (text) => {
  // 从HTML中提取纯文本
  const tempDiv = document.createElement('div')
  tempDiv.innerHTML = text
  const plainText = tempDiv.textContent || tempDiv.innerText || ''
  
  navigator.clipboard.writeText(plainText)
    .then(() => {
      ElMessage.success('已复制到剪贴板')
    })
    .catch(err => {
      console.error('复制失败:', err)
      ElMessage.error('复制失败')
    })
}

// 处理Enter键
const handleEnter = () => {
  if (isGenerating.value) {
    // 生成中按Enter终止
    stopGenerating()
  } else if (textarea2.value.trim() || selectedFiles.value.length > 0) {
    // 非生成状态且有内容则提交
    handleQuestion()
  }
}

// 处理Ctrl+Enter插入换行
const insertNewLine = (event) => {
  textarea2.value += '\n'
  event.preventDefault()
}


const handleSingleChar = () => {
  if(selectedFiles.value.length == 0) {
    ElMessage.error('请先上传想要查询的甲骨文图片')
     return
  }
  textarea2.value = '请给我解释一下图片上的甲骨文字是什么意思？'
  handleQuestion()
  // 这里添加单字识别功能逻辑
}

const handleCharSearch = () => {
   if(selectedFiles.value.length == 0) {
    ElMessage.error('请先上传想要查询的甲骨文图片')
     return
  }
  textarea2.value = '请给我说明一下图片上的甲骨文字在哪里出现过？'
  handleQuestion()
 
}

const handleRubbingGen = () => {
   if(selectedFiles.value.length == 0) {
    ElMessage.error('请先上传想要查询的甲骨文图片')
    return
  }
  textarea2.value = '识别甲骨单字图片(拓片,摹本),请给我生成清晰的甲骨文摹本？'
  handleQuestion()

}

const handleRubbingSearch = () => {
  if(selectedFiles.value.length == 0) {
    ElMessage.error('请先上传想要查询的甲骨图片')
     return
  }
  textarea2.value = '请给我说明一下这个拓片的在哪里出现过？'
  handleQuestion()
}


// const yp = ref(false)
const regenerateResponse = async (aiMsgId) => {
  const aiMsgIndex = messages.value.findIndex(msg => msg.id === aiMsgId)
  if (aiMsgIndex === -1) return

  const userMsg = messages.value[aiMsgIndex - 1]
  if (!userMsg || userMsg.type !== 'user') {
    ElMessage.error('未找到对应的问题消息')
    return
  }


  textarea2.value = userMsg.textContent || ''
  
  // 如果有图片，重新设置selectedFiles
  if (userMsg.images && userMsg.images.length > 0) {
    console.log('用户出现上传图片',userMsg.images[0])
  console.log('用户从新上传图片file',userMsg.images[0].file)

    selectedFiles.value = userMsg.images.map(img => ({
      ...img,
    }))
  } else {
    selectedFiles.value = []
  }

  await scrollToBottom()
  handleQuestion()
}
// 终止生成
const stopGenerating = async () => {
  const token = userStore.token;
  if (!token) return;

  if (!sessionId.value) return;

    if(userquestion.isNew){
     userquestion.isNew=false
     }
        const apiUrl = `${baseUrl}/chat/stop`;
  try {
    const res = await fetch(apiUrl, {
      method: "POST",
      headers: {
        Authorization: `Bearer ${token}`,
        "Content-Type": "application/x-www-form-urlencoded"
      },
      body: new URLSearchParams({ session_id: sessionId.value })
    });
    const result = await res.json();
    if (result.code === 200) {
      isGenerating.value = false;
      userquestion.isGenerating=false;
    } else {
      ElMessage.warning(result.message || "中止失败");
    }
  } catch (err) {
    ElMessage.error("中止请求异常");
  }
};


const handleQuestion = async () => {
let questionText = textarea2.value.trim();
  if (!questionText && selectedFiles.value.length === 0) return;

  const token = userStore.token;

  // 在消息列表添加用户消息
  const userMsg = {
    id: Date.now(),
    type: "user",
    textContent: questionText,
    images: selectedFiles.value.map(file => ({
      url: file.url,
      name: file.name,
      file: file.file
    })),
  };
  console.log('用户消息',userMsg)
  messages.value.push(userMsg);

  scrollToBottom();

  const formData = new FormData();
  formData.append("question", questionText);
  formData.append("session_id", sessionId.value);

  if (selectedFiles.value.length > 0) {
  const firstFile = selectedFiles.value[0];
    console.log('用户上传图片file是',firstFile.file)
  if (firstFile.file) { // 检查file对象是否存在
    formData.append("image", firstFile.file);
  } else {
    console.warn("文件对象不存在，无法添加到FormData");
  }
}

  // 修改后的AI消息结构
  const aiMsg = {
    id: Date.now() + 1,
    type: "ai",
    content: "",           // 最终答案
    thoughtContent: "",    // 纯思考内容
    toolContent: "",       // 工具内容
    isThinking: true,      // 加载状态
    showThought: true,     // 显示思考内容
    showAnswer: false,     // 显示答案
    showTool: false,       // 显示工具
    answerStarted: false,  // 是否进入答案阶段
    wasInterrupted: false,  // 新增：是否被中断
     isFolded: false      // 新增：是否折叠
  };
  messages.value.push(aiMsg);
  currentAIMessageId.value = aiMsg.id;
  isGenerating.value = true;
  userquestion.isGenerating=true;
  textarea2.value = "";
  selectedFiles.value = [];
   const ai = messages.value.find(m => m.id === currentAIMessageId.value);
   const apiUrl = `${baseUrl}/chat/stream`;
  try {
    const response = await fetch(apiUrl, {
      method: "POST",
      headers: { Authorization: `Bearer ${token}` },
      body: formData
    });
    if (!response.ok) throw new Error("请求失败，状态码：" + response.status);

    const reader = response.body?.getReader();
    const decoder = new TextDecoder("utf-8");
    let buffer = "";

    while (reader) {
      const { done, value } = await reader.read();
    

      buffer += decoder.decode(value, { stream: true });
      const lines = buffer.split("\n\n");
      buffer = lines.pop() || "";

      for (const line of lines) {
        if (!line.startsWith("data: ")) continue;
        
          if (!ai) continue;
        const raw = line.slice(6).trim();

        if (raw === "[DONE]") {
          // 立即触发结束逻辑
         if (ai.toolContent && !ai.wasInterrupted) {
             ai.showAnswer = false;
              ai.showTool = true;
            }
             isGenerating.value = false;
               userquestion.isGenerating=false;
            if(userquestion.isNew){
              userquestion.isNew=false
            }
             return; // 直接退出循环
          }

          if (done) {
            isGenerating.value = false;
                 userquestion.isGenerating=false;
            if(userquestion.isNew){
              userquestion.isNew=false
            }
            return;
          }

        try {
          const data = JSON.parse(raw);
          // 检查是否中断响应
          if (data.type === "answer" && data.content.includes("回答已中断")) {
        
            ai.wasInterrupted = true;
            isGenerating.value = false;
                 userquestion.isGenerating=false;
            ai.isThinking = false;
            // 检查是否完全没有内容
                if(userquestion.isNew){
                 userquestion.isNew=false
            }
            const hasNoContent = !ai.thoughtContent && !ai.content;
            if (hasNoContent) {
                 ai.thoughtContent += data.content;
                    scrollToBottom();

            } else {
              // 保留现有内容
              ai.showThought = !!ai.thoughtContent;
              ai.showAnswer = !!ai.content;
              ai.showTool = !!ai.toolContent; 
            }
           ElMessage('已终止回答')
            return; 
          }

       
          // 正常处理逻辑
         if (!ai.answerStarted && !ai.wasInterrupted) {
            if (data.type === "reasoning") {
                 ai.isThinking = false;
              ai.thoughtContent += data.content;
              // console.log("shikao",ai.thoughtContent)
               ai.thoughtContent = processMessage(ai.thoughtContent)
            }
            else if (data.type === "tool") {
              // ai.toolContent += data.content;
            }
            else if (data.type === "answer" && data.content.trim() !== "") {
              ai.answerStarted = true;
              ai.showThought = false;
              ai.showAnswer = true;
              ai.content += data.content;
              ai.content = processMessage(ai.content)
            }
          }
          else if (ai.answerStarted && !ai.wasInterrupted) {
            if (data.type === "answer") {
              ai.content += data.content;
               ai.content = processMessage(ai.content)
            }
          }
          await nextTick();
          scrollToBottom();
        } catch (err) {
          console.warn("解析失败:", err);
        }
      }
    }
  } catch (err) {
    if (!aiMsg.wasInterrupted) {
      ElMessage.error("AI 回复失败");
      console.log("详细的错误原有",err.message)
       console.error("API Error Details:", {
    message: err.message,
    stack: err.stack,
    response: err.response
  });
    }
    ai.isThinking = false;
    isGenerating.value = false;
      userquestion.isGenerating=false;
  }
};



// 滚动到消息底部
const scrollToBottom = async () => {
  await nextTick()
  if (messagesWrap.value) {
    messagesWrap.value.scrollTop = messagesWrap.value.scrollHeight
  }
}

// 打开文件选择对话框
const openFileDialog = () => {
  if (!isGenerating.value) {
    fileInput.value?.click()
  }
}

// 处理文件上传
const handleFileUpload = async (event) => {
  const files = Array.from(event.target.files)
  if (!files.length) return

  if (selectedFiles.value.length + files.length >1) {
    ElMessage.error('最多只能上传1张图片')
    event.target.value = ''
    return
  }

  event.target.value = ''

  const uploadPromises = files.map(file => {
    return new Promise((resolve) => {
      if (!file.type.startsWith('image/')) {
        ElMessage.error(`文件"${file.name}"不是有效的图片格式`)
        resolve(null)
        return
      }
      
      if (file.size > 5 * 1024 * 1024) { 
        ElMessage.error(`文件"${file.name}"超过大小限制 (5MB)`)
        resolve(null)
        return
      }

      const isDuplicate = selectedFiles.value.some(
        f => f.name === file.name && f.size === file.size
      )
      
      if (isDuplicate) {
        ElMessage.warning(`文件"${file.name}"已存在`)
        resolve(null)
        return
      }

      const reader = new FileReader()
      reader.onload = () => {
        resolve({
          id: fileIdCounter++,
          name: file.name,
          size: file.size,
          file: file,
          url: reader.result
        })
      }
      reader.onerror = () => {
        ElMessage.error(`文件"${file.name}"读取失败`)
        resolve(null)
      }
      reader.readAsDataURL(file)
    })
  })

  const newFiles = (await Promise.all(uploadPromises)).filter(Boolean)
 console.log(newFiles)
  if (newFiles.length > 0) {
    selectedFiles.value = [...selectedFiles.value,...newFiles]
    ElMessage.success(`成功添加 ${newFiles.length} 个文件`)
  }

}

// 移除已选择的文件
const removeFile = (index) => {
  selectedFiles.value.splice(index, 1)
  ElMessage.success('文件已移除')
}

// 格式化文件大小
const formatFileSize = (bytes) => {
  if (bytes === 0) return '0 Bytes'
  const k = 1024
  const sizes = ['Bytes', 'KB', 'MB', 'GB']
  const i = Math.floor(Math.log(bytes) / Math.log(k))
  return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) +'' + sizes[i]
}

// 截断长文件名
const truncateFileName = (name) => {
  const maxLength = 20
  if (name.length > maxLength) {
    return name.substring(0, maxLength) + '...'
  }
  return name
}

// 计算图片尺寸和气泡形状
const calculateImageSize = (imgInfo, event, msgIndex, imgIndex) => {
  const img = event.target
  const width = img.naturalWidth
  const height = img.naturalHeight
  const aspectRatio = `${width}/${height}`
  
  imageSizes.value[`${msgIndex}-${imgIndex}`] = {
    aspectRatio,
    width,
    height
  }
  
  nextTick(() => {
    calculateImageLayout(msgIndex)
  })
}

// 计算图片布局
const calculateImageLayout = (msgIndex) => {
  const container = imageContainers.value[msgIndex]
  if (!container) return
  
  const containerWidth = container.offsetWidth
  const maxWidth = containerWidth * 0.95
  
  const images = Array.from(container.querySelectorAll('.adaptive-chat-img'))
  if (!images.length) return
  
  images.forEach(img => {
    img.style.width = ''
    img.style.display = ''
    img.style.margin = ''
  })
  
  let totalWidth = 0
  images.forEach(img => {
    const imgSize = imageSizes.value[`${msgIndex}-${images.indexOf(img)}`]
    if (imgSize) {
      const [w, h] = imgSize.aspectRatio.split('/').map(Number)
      const ratio = w / h
      const maxImgHeight = 200
      const imgWidth = Math.min(ratio * maxImgHeight, maxWidth)
      totalWidth += imgWidth
    }
  })
  
  if (totalWidth <= maxWidth) {
    let actualTotalWidth = 0
    const imgWidths = []
    
    images.forEach(img => {
      const imgSize = imageSizes.value[`${msgIndex}-${images.indexOf(img)}`]
      if (imgSize) {
        const [w, h] = imgSize.aspectRatio.split('/').map(Number)
        const ratio = w / h
        const imgWidth = ratio * 200
        imgWidths.push(imgWidth)
        actualTotalWidth += imgWidth
      }
    })
    
    const scaleRatio = maxWidth / actualTotalWidth
    
    images.forEach((img, i) => {
      img.style.width = `${imgWidths[i] * scaleRatio}px`
      img.style.display = 'inline-block'
      img.style.marginRight = '8px'
    })
    
    if (images.length > 0) {
      images[images.length - 1].style.marginRight = '0'
    }
  } else {
    container.style.display = 'grid'
    container.style.gridTemplateColumns = 'repeat(auto-fill, minmax(120px, 1fr))'
    container.style.gap = '10px'
  }
}
//历史记录
// if (sessionId) {
// watch(
//   () => userStore.sessionId,
//   async (newVal, oldVal) => {
//     if (!newVal) return;
//     console.log("nh")
//     // 重置当前状态
//     messages.value = [];
//     isGenerating.value = false;
//     textarea2.value = '';
//     selectedFiles.value = [];
    
//     // 加载新会话历史
//     await fetchSessionHistory(newVal);
    
//     // 确保滚动到底部
//     await nextTick();
//     scrollToBottom();
//   },
//   { immediate: true }  // 确保初始加载
// );
// }
// 监听窗口大小变化
watch(() => window.innerWidth, () => {
  messages.value.forEach((_, idx) => {
    if (messages.value[idx].type === 'user' && messages.value[idx].images) {
      calculateImageLayout(idx)
    }
  })
})
defineExpose({ fetchSessionHistory });

const downloadImage = () => {
  const link = document.createElement('a');
  link.href = previewImgData.value.url;
  link.download = previewImgData.value.name || 'image.png';
  document.body.appendChild(link);
  link.click();
  document.body.removeChild(link);
};

</script>


<style scoped>
.text :deep(p),
.text :deep(ul),
.text :deep(ol),
.text :deep(li) {
  margin: 0;
  padding: 0;
}
 
/* --- 2. 列表结构与间距 --- */
 
/* 为所有列表设置一个统一且合适的缩进 */
.text :deep(ol),
.text :deep(ul) {
  padding-left: 1.8em; /* 你可以微调这个值 */
}
 
/* 
  为每个列表项（<li>）的底部增加一点间距，
  这样主标题和子列表之间、列表项和列表项之间都会有呼吸感。
*/
.text :deep(li) {
  margin-bottom: 0em;
}
/* --- 3. 【核心修复】对齐 Marker --- */
 
/*
  这就是解决对齐问题的魔法！
  我们将<li>内的<p>从“块”模式改为“行内”模式。
  这会强制<p>内的文本和<li>的::marker在同一条基线上对齐。
*/
.text :deep(ol li p) {
  display: contents;
}
 
/*
  当一个子列表(ul)紧跟在一个标题段落(p)后面时，
  为这个子列表顶部也增加一点间距，让布局更清晰。
*/
.text :deep(li > p + ul) {
  margin-top: 0.6em;
}
 
 
/* --- 4. 图片和链接样式 (保持不变) --- */
.text :deep(img) {
  vertical-align: middle;
  max-height: 2.2em;
  margin: -0.2em 0.2em 0;
}
.text :deep(a) {
  color: #1e63b6;
  text-decoration: none;
}
.text :deep(a:hover) {
  text-decoration: underline;
}
/* 新增图片预览样式 */
.preview-container {
  width: 100%;
  height: 60vh;
  overflow: hidden;
  display: flex;
  align-items: center;
  justify-content: center;
  background-color: #f5f5f5;
  border-radius: 8px;
  position: relative;
  cursor: grab;
  touch-action: none;
}

.preview-container.grabbing {
  cursor: grabbing;
}

.preview-content {
  width: 50%;
  height: 50%;
  will-change: transform;
  user-select: none;
  pointer-events: none;
  transform-origin: center center;
  object-fit: contain;
}

.preview-controls {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 10px;
  padding: 10px;
  background-color: rgba(255, 255, 255, 0.9);
  border-radius: 20px;
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
}

.zoom-info {
  margin-left: 10px;
  font-size: 14px;
  color: #666;
}

/* 控制栏样式 */
.control-bar {
  width: min(64%, 1200px);
  margin: 10px auto 0;
  padding: 8px 15px;
  display: flex;
  justify-content: flex-end;
  align-items: center;
}

/* AI消息组样式 */
.ai-message-group {
  display: flex;
  flex-direction: column;
  gap: 12px;
  margin-bottom: 32px;
}


/* 思考消息气泡样式 */
.thought-message {
  background: linear-gradient(135deg, #f8fafb, #eef2f5); /* 调整为更中性的灰白色渐变 */
  border-radius: 18px 18px 18px 0;
  box-shadow: 0 2px 8px rgba(70, 76, 85, 0.08); /* 阴影色调整为中性灰 */
  border: 1px solid #e2e8f0; /* 边框改为浅灰色 */
}

/* 思考消息头部样式 */
.thought-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  cursor: pointer;
  padding: 0.2em 0;
  border-bottom: 1px dashed #d1d5db;
  margin-bottom: 0.8em;
}

/* 折叠图标样式 */
.fold-icon {
  color: #8B5A2B;
  font-size: 16px;
  transition: transform 0.2s ease;
  margin-left: 8px;
}

/* 思考标题样式 */
.thought-title {
  
  font-size: 1.1em;
  font-weight: 600;
  color: #4b5563; /* 深灰色替代蓝色 */
  margin:  0;
  padding: 0;
  display: inline;
  letter-spacing: 0.05em;
}

/* 工具消息气泡样式 */
.tool-message {
 max-width: 100%;
  word-break: break-word;
   color: #5a3e2b; /* 棕色文字 */
  font-family: monospace; /* 工具内容使用等宽字体 */
  background-color: rgba(0,0,0,0.05); /* 轻微背景色区分 */
  background: linear-gradient(135deg, #fff5f0, #ffe5dc);
  color: #9b2c2c;
  border-radius: 18px 18px 18px 0;
  box-shadow: 0 2px 8px rgba(155, 44, 44, 0.1);
  border: 1px solid #fed7d7;
}

/* 答案消息气泡样式 */
.answer-message {
  background: linear-gradient(135deg, #f8f4f0, #f0e6dc);
  color: #5a2b36;
  border-radius: 18px 18px 18px 0;
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.05);
  border: 1px solid #e2d5c3;
}

.message-content li {
  white-space: normal;
  word-break: break-word;

}

.answer-message .text{
    line-height: 1.7;
    font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
  white-space: pre-wrap; /* 保留换行符但自动换行 */
  word-wrap: break-word; /* 允许长单词换行 */
  overflow-wrap: break-word; /* 更智能的断词 */
  word-break: break-word; /* 中文换行优化 */
}


.answer-message :deep(code) {
  background-color: rgba(229, 231, 235, 0.7); 
  color: #374151;
  padding: 0.2em 0.4em;
  border-radius: 3px;
  font-family: "SFMono-Regular", Consolas, "Liberation Mono", Menlo, monospace;
  font-size: 0.9em;
  white-space: pre-wrap;
}

/* 思考内容样式 */
.thought-content {
  line-height: 1.7;
  color: #4b5563; /* 主文字改为深灰色 */
  font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
  white-space: pre-wrap;
  word-wrap: break-word;
  overflow-wrap: break-word;
  word-break: break-word;
  font-size: 0.95em;
  transition: all 0.3s ease;
  overflow: hidden;
}

/* 思考内容中的代码块样式 */
.thought-content :deep(code) {
  background-color: rgba(229, 231, 235, 0.7); /* 浅灰色背景 */
  color: #374151; /* 深灰色代码文字 */
  padding: 0.2em 0.4em;
  border-radius: 3px;
  font-family: "SFMono-Regular", Consolas, "Liberation Mono", Menlo, monospace;
  font-size: 0.9em;
  white-space: pre-wrap;
}

/* 思考内容中的链接样式 */
.thought-content :deep(a) {
  color: #5b21b6; /* 改用深紫色保持可点击性 */
  text-decoration: none;
  border-bottom: 1px dotted #c4b5fd; /* 浅紫色下划线 */
}

.thought-content :deep(a:hover) {
  color: #6d28d9; /* 悬停时稍亮的紫色 */
  border-bottom-style: solid;
}

.language-json {
    white-space: pre-wrap;
    /* word-wrap: break-word; */
    overflow-wrap: break-word;
    word-break: break-word;
}



/* 工具内容样式 */
.tool-content {
 max-width: 100%;
  overflow-wrap: break-word;
  word-break: break-word;
  line-height: 1.3;
  white-space: pre-wrap;
  font-family: 'Courier New', monospace; /* 更优雅的等宽字体 */
  padding: 4px 6px;
  border-radius: 6px;
  font-size: 0.95em;
  white-space: pre-wrap; /* 保留换行符但自动换行 */
  word-wrap: break-word; /* 允许长单词换行 */
  overflow-wrap: break-word; /* 更智能的断词 */
  word-break: break-word; /* 中文换行优化 */
}


/* 思考中状态样式 */
.dot-pulse {
  display: flex;
  gap: 4px;
  height: 14px;
  align-items: center;
}

.dot-pulse span {
  width: 5px;
  height: 3.5px;
  border-radius: 50%;
  background-color: #8B5A2B;
  display: inline-block;
  animation: pulse 1.2s infinite ease-in-out both;
  opacity: 0.7;
}

.dot-pulse span:nth-child(1) { 
  animation-delay: -0.32s; 
  background-color: #D2B48C; /* 浅棕色 */
}
.dot-pulse span:nth-child(2) { 
  animation-delay: -0.16s; 
  background-color: #BC8F8F; /* 中等棕色 */
}
.dot-pulse span:nth-child(3) { 
  background-color: #8B5A2B; /* 深棕色 */
}

@keyframes pulse {
  0%, 100% { 
    transform: scale(0.5);
    opacity: 0.3;
  }
  50% { 
    transform: scale(1.1);
    opacity: 1;
  }
}

/* 页面整体容器 */
.page-wrapper {
  position: relative;
  width: 100%;
  height: 100vh;
  display: flex;
  flex-direction: column;
  justify-content: flex-end;
  overflow: hidden;
  font-family: 'Microsoft YaHei', sans-serif;
  background-color: #fefcf9;
}

/* 对话内容区域 */
.chat-messages {
  flex: 1; 
  overflow-y: auto;
  padding: clamp(15px, 2vw, 20px);
  background-color: #fff9f2;
  border: 1px solid #f0e6de;
  border-radius: 8px;
  margin-bottom: 10px;
  box-sizing: border-box;
  scroll-behavior: smooth;
  width: min(64%, 1200px); 
  margin: 0 auto;
}

/* 消息组 */
.message-group {
  margin-bottom: 32px;
  position: relative;
}

/* 消息气泡通用样式 */
.chat-message {
  max-width: 100%;
  min-width: 50px;
  width: fit-content;
  margin: 4px 0;
  padding: clamp(8px, 1vw, 12px) clamp(12px, 1.5vw, 16px);
  border-radius: 8px;
  line-height: 1.5;
  word-break: break-word;
  animation: fadeIn 0.3s ease;
  position: relative;
}

.chat-message.ai-message {
  background: linear-gradient(135deg, #F8F4F0, #F0E6DC);
    color: rgba(0, 0, 0, 0.85); /* 85%不透明度黑 */
  font-weight: 500;   
  border-radius: 18px 18px 18px 0;
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.05);
  border: 1px solid #e2d5c3;
  margin: 4px 0;
  padding: clamp(10px, 1vw, 12px) clamp(18px, 2vw, 25px);
  position: relative;
}


/* 用户消息气泡 */
.user-message {
  background: linear-gradient(135deg, #8B5A2B, #D4A373);
  color: white;
  margin-left: auto;
  border-radius: 18px 18px 0 18px;
  box-shadow: 
    0 2px 8px rgba(139, 90, 43, 0.2),
    inset 0 1px 1px rgba(255, 255, 255, 0.1);
  position: relative;
}

/* 气泡装饰元素 */
.user-message::before {
  content: "";
  position: absolute;
  top: 0;
  right: 0;
  width: 30px;
  height: 30px;
  background: radial-gradient(circle at 0% 100%, rgba(0,0,0,0.03) 0%, transparent 70%);
  border-radius: 0 100% 0 0;
}

.ai-message::after {
  content: "";
  position: absolute;
  bottom: 0;
  left: 0;
  width: 30px;
  height: 30px;
  background: radial-gradient(circle at 100% 0%, rgba(255,255,255,0.2) 0%, transparent 70%);
  border-radius: 0 0 0 100%;
}

/* 消息文本样式 */
.message-content.text {
  position: relative;
  z-index: 1;
  line-height: 1.6;
  text-shadow: 0 1px 1px rgba(0, 0, 0, 0.05);
  margin-left: 20px;
}


/* 标题与正文对齐 */
.message-content h3,
.message-content h4 {
  padding-left: 2.5em;
  text-indent: -1.8em;
  margin: 1em 0 0.5em;
}

/* 响应式调整 */
@media (max-width: 768px) {
  .message-content ul,
  .message-content ol {
    padding-left: 2em;
  }
  .message-content ol li::before {
    left: -1.5em;
  }
}

.user-message.text {
  text-shadow: 0 1px 1px rgba(0, 0, 0, 0.1);
}

/* 图片气泡样式 */
.image-bubble {
  max-width: 78%;
  padding: 6px;
  background: linear-gradient(135deg, #8B5A2B, #D4A373);
  border-radius: 14px;
  box-shadow: 
    0 4px 12px rgba(139, 90, 43, 0.2),
    inset 0 1px 1px rgba(255, 255, 255, 0.1);
}

/* 自适应图片容器 */
.adaptive-image-container {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
}

/* 自适应图片样式 */
.adaptive-chat-img {
  display: block;
  max-height: 100px;
  object-fit: contain;
  border-radius: 8px;
  cursor: pointer;
  border: 2px solid rgba(255, 255, 255, 0.2);
  aspect-ratio: var(--aspect-ratio, 1/1);
}

/* 消息操作按钮 */
.message-actions {
  position: absolute;
  display: flex;
  gap: 8px;
  opacity: 0.9;
  transition: all 0.2s ease;
  z-index: 10;
  filter: drop-shadow(0 1px 2px rgba(0, 0, 0, 0.1));
}

.message-actions.user-actions {
  /* Position remains unchanged */
  flex-direction: row-reverse;
  gap: 6px;
  right: 1px;
  bottom: -28px;
}

.message-actions.user-actions .action-btn {
  /* Frosted glass effect */
  background: rgba(255, 255, 255, 0.9);
  backdrop-filter: blur(10px);
  -webkit-backdrop-filter: blur(10px);
  border: 1px solid rgba(255, 255, 255, 0.3);
  box-shadow: 
    0 2px 8px rgba(139, 90, 43, 0.15),
    inset 0 1px 1px rgba(255, 255, 255, 0.2);
}

.message-actions.user-actions .action-btn:hover {
  background: rgba(255, 255, 255, 0.95);
  transform: translateY(-3px) scale(1.1);
  box-shadow: 
    0 4px 12px rgba(139, 90, 43, 0.25),
    inset 0 1px 1px rgba(255, 255, 255, 0.3);
}

.message-actions.user-actions .action-btn:active {
  transform: translateY(0) scale(0.98);
}

/* Edit button */
.message-actions.user-actions .edit-btn {
  background: rgba(235, 248, 240, 0.9);
}

.message-actions.user-actions .edit-btn .el-icon {
  color: #2e8b57;
}

.message-actions.user-actions .edit-btn:hover {
  background: rgba(220, 245, 230, 0.95);
}

/* Copy button */
.message-actions.user-actions .copy-btn {
  background: rgba(248, 244, 240, 0.9);
}

.message-actions.user-actions .copy-btn .el-icon {
  color: #8B5A2B;
}

.message-actions.user-actions .copy-btn:hover {
  background: rgba(240, 230, 220, 0.95);
}

.message-actions.ai-actions {
  /* Position remains unchanged */
  left: 15px;
  bottom: 7px;
}

.message-actions.ai-actions .action-btn {
  /* Semi-transparent frosted background */
  background: rgba(248, 244, 240, 0.85);
  backdrop-filter: blur(8px);
  -webkit-backdrop-filter: blur(8px);
  border: 1px solid rgba(210, 180, 140, 0.2);
  box-shadow: 
    0 2px 6px rgba(0, 0, 0, 0.1),
    inset 0 1px 1px rgba(255, 255, 255, 0.3);
}

.message-actions.ai-actions .action-btn:hover {
  background: rgba(255, 255, 255, 0.95);
  transform: translateY(-3px) scale(1.1);
  box-shadow: 
    0 4px 10px rgba(0, 0, 0, 0.15),
    inset 0 1px 1px rgba(255, 255, 255, 0.4);
}

/* Copy button */
.message-actions.ai-actions .copy-btn {
  background: rgba(245, 240, 230, 0.85);
}

.message-actions.ai-actions .copy-btn .el-icon {
  color: #5a3e2b;
}

.message-actions.ai-actions .copy-btn:hover {
  background: rgba(255, 250, 240, 0.95);
}

/* Regenerate button */
.message-actions.ai-actions .regenerate-btn {
  background: rgba(230, 245, 235, 0.85);
}

.message-actions.ai-actions .regenerate-btn .el-icon {
  color: #2e8b57;
}

.message-actions.ai-actions .regenerate-btn:hover {
  background: rgba(220, 240, 230, 0.95);
}

/* Disabled state */
.message-actions.ai-actions .regenerate-btn.disabled-btn {
  background: rgba(230, 230, 230, 0.7) !important;
  cursor: not-allowed;
}

.message-actions.ai-actions .regenerate-btn.disabled-btn .el-icon {
  color: #999 !important;
}

.action-btn {
  /* Base styles */
  width: 28px;
  height: 28px;
  border-radius: 50%;
  display: flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
  transition: all 0.25s cubic-bezier(0.25, 0.8, 0.25, 1);
}

.action-btn .el-icon {
  font-size: 14px;
  transition: all 0.2s ease;
  position: relative;
  z-index: 1;
}

.action-btn:hover .el-icon {
  transform: scale(1.15);
}

.action-btn::after {
  content: '';
  position: absolute;
  top: 50%;
  left: 50%;
  width: 5px;
  height: 5px;
  background: rgba(255, 255, 255, 0.5);
  opacity: 0;
  border-radius: 100%;
  transform: scale(1, 1) translate(-50%, -50%);
  transform-origin: 50% 50%;
}

.action-btn:active::after {
  animation: ripple 0.6s ease-out;
}

@keyframes ripple {
  0% {
    transform: scale(0, 0);
    opacity: 0.5;
  }
  100% {
    transform: scale(20, 20);
    opacity: 0;
  }
}

.disabled-btn {
  /* Disabled state */
  background: rgba(230, 230, 230, 0.7) !important;
  cursor: not-allowed !important;
  box-shadow: none !important;
}

.disabled-btn .el-icon {
  color: #999 !important;
}

.disabled-btn:hover {
  transform: none !important;
  background: rgba(230, 230, 230, 0.7) !important;
}

/* 底部区域 */
.fixed-bottom {
  width: min(64%, 1200px);
  margin: 0 auto 11vh; 
  padding: 5px 5px;
  box-sizing: border-box;
  border-radius: 15px;
  border-top: 1px solid #f0e6de;
  z-index: 100;
  box-shadow: 0 -2px 10px rgba(0, 0, 0, 0.05);
}

/* 文件显示区域样式 */
.files-info {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  margin-bottom: 12px;
  max-height: 80px;
  overflow-y: auto;
}

/* 文件项样式 */
.file-item {
  width: calc(50% - 4px);
  box-sizing: border-box;
}

/* 文件标签样式 */
.file-tag {
  cursor: pointer;
  background: linear-gradient(to right, #8B4513, #d4a373);
  color: white;
  border: none;
  padding: 4px 10px;
  border-radius: 8px;
  font-size: 12px;
  display: flex;
  align-items: center;
  justify-content: space-between;
  width: 100%;
  overflow: hidden;
}

/* 文件名样式 */
.file-name {
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  flex: 1;
  min-width: 0;
}

/* 文件大小样式 */
.file-size {
  font-size: 0.8em;
  opacity: 0.8;
  margin-left: 5px;
  white-space: nowrap;
}

/* 关闭按钮样式 */
.close-icon {
  font-size: 14px;
  margin-left: 8px;
  cursor: pointer;
  width: 16px;
  height: 16px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  border-radius: 50%;
}

/* 输入框区域样式 */
.input-area {
  position: relative;
  border-radius: 8px!important;
  border: 2px solid #d4a373;
  background-color: #fffdfb;
}
.input-area:focus-within {
  border-color: #b58863;
  background-color: #fff5f2;
  box-shadow: 0 0 0 2px rgba(181, 136, 99, 0.2);
}

/* 自定义文本域样式 */
.custom-textarea :deep(.el-textarea__inner) {
  width: 100%!important;
  padding: 1rem 1rem 1rem;
  border-radius: 8px!important;
  font-size: 14px;
  line-height: 1.5;
  color: #5a3e2b;
  resize: none!important;
  box-shadow: none;
  overflow-y: auto;
  box-sizing: border-box;
  scrollbar-width: thin;
  min-height: 100px!important; 
  max-height: 210px !important;
}

.custom-textarea :deep(.el-textarea__inner:focus) {
  border-color: #b58863;
  background-color: #fff5f2;
  outline: none;
}

.custom-textarea :deep(.el-textarea__inner:disabled) {
  background-color: #fffdfb;
  cursor: not-allowed;
}

.custom-textarea :deep(.el-textarea__inner::placeholder) {
  color: #b7a08e;
  font-style: italic;
  font-size: 15px;
  opacity: 0.8;
}

/* 左侧按钮区域 */
.buttons-left {
  position: static;
  margin-left: 0.5rem; 
  margin-bottom: 0.5rem;
  display: flex;
  gap: 0.5rem;
  z-index: 2;
  align-items: center;
  min-height: 1rem;
  flex-wrap: wrap;
}

.rect-button {
  padding: 0.5rem 1rem;
  background: linear-gradient(145deg, #f9f3ec, #ebddcc);
  border-radius: 0.5rem;
  cursor: pointer;
  position: relative;
  box-shadow: 
    0 3px 8px rgba(139, 69, 19, 0.12),
    inset 0 1px 3px rgba(255, 255, 255, 0.9);
  border: 1px solid #e0c9b8;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 0.9rem;
  font-weight: 500;
  color:#8B4513;
  transform: translateY(0);
  transform-origin: center;
  user-select: none;
}

.rect-button::before {
  content: '';
  position: absolute;
  top: 1px;
  left: 1px;
  right: 1px;
  bottom: 1px;
  border-radius: 0.65rem;
  background: linear-gradient(
    180deg,
    rgba(255, 255, 255, 0.2) 0%,
    rgba(255, 255, 255, 0) 100%
  );
  pointer-events: none;
}

.rect-button span {
  white-space: nowrap;
  position: relative;
  z-index: 1;
}

.rect-button:hover {
  background: linear-gradient(145deg, #f5e9dd, #e0c9b8);
  box-shadow: 
    0 6px 12px rgba(139, 69, 19, 0.18),
    inset 0 1px 3px rgba(255, 255, 255, 0.7);
}

.rect-button:active {
  transform: translateY(-1px) scale(0.99);
  box-shadow: 
    0 2px 5px rgba(139, 69, 19, 0.15),
    inset 0 2px 4px rgba(0, 0, 0, 0.12);
}

/* 右侧按钮区域样式 */
.buttons {
  position: absolute;
  right: 10px;
  bottom: 10px;
  display: flex;
  gap: 8px;
  z-index: 2;
}

/* 上传按钮样式 */
.circle2 {
  width: 32px;
  height: 32px;
  background: linear-gradient(145deg, #f9f3ec, #ebddcc);
  border-radius: 50%;
  cursor: pointer;
  position: relative;
  box-shadow: 
    0 2px 5px rgba(139, 69, 19, 0.1),
    inset 0 1px 2px rgba(255, 255, 255, 0.8);
  border: 1px solid #e0c9b8;
  display: flex;
  align-items: center;
  justify-content: center;
}

.circle2.disabled {
  background: linear-gradient(145deg, #e8e8e8, #d8d8d8);
  cursor: not-allowed;
  opacity: 0.7;
}

/* 上传按钮图标 */
.icron3 {
  color: #8B4513;
  font-size: 16px;
}

/* 发送/停止按钮样式 */
.circle {
  width: 32px;
  height: 32px;
  border-radius: 50%;
  cursor: pointer;
  position: relative;
  box-shadow: 
    0 2px 5px rgba(139, 69, 19, 0.1),
    inset 0 1px 2px rgba(255, 255, 255, 0.5);
  border: none;
  display: flex;
  align-items: center;
  margin-right: 10px;
  justify-content: center;
}

/* 输入框有内容但未上传文件时的按钮样式 */
.circle.has-content:not(.stop-btn) {
  background: linear-gradient(145deg, #d4a373, #b58863);
}

.circle:not(.has-content) {
  background: linear-gradient(145deg, #e8e8e8, #d8d8d8);
}

.circle.disabled {
  background: #e8e8e8!important;
  cursor: not-allowed;
  box-shadow: none;
}

/* 终止生成按钮样式 */
.circle.stop-btn {
  background: linear-gradient(145deg, #d4a373, #b58863);
}

/* 发送/停止按钮图标 */
.icon2 {
  color: white;
}

/* 动画效果 */
@keyframes fadeIn {
  from { opacity: 0; transform: translateY(10px); }
  to { opacity: 1; transform: translateY(0); }
}


@media (min-width:2300px) {
  .fixed-bottom{ margin: 0 auto 7.5vh; }
  /* 聊天相关 */
  .chat-messages,
  .fixed-bottom,
  .control-bar {
    width: min(55%, 1400px);
  }
  .chat-message {
    font-size: 16px;
  }
  .adaptive-chat-img {
    max-height: 140px;
  }
    .custom-textarea :deep(.el-textarea__inner) {

  min-height: 150px!important; 
  max-height: 270px !important;
}
}

@media (min-width: 2100px) and (max-width: 2300px){
  .fixed-bottom{ margin: 0 auto 7.6vh; }
  /* 聊天相关 */
  .chat-messages,
  .fixed-bottom,
  .control-bar {
    width: min(55%, 1400px);
  }
  .chat-message {
    font-size: 16px;
  }
  .adaptive-chat-img {
    max-height: 140px;
  }
    .custom-textarea :deep(.el-textarea__inner) {

  min-height: 140px!important; 
  max-height: 260px !important;
}
}



@media (min-width: 1920px) and (max-width: 2099px){
  .fixed-bottom{ margin: 0 auto 8.1vh; }
  /* 聊天相关 */
  .chat-messages,
  .fixed-bottom,
  .control-bar {
    width: min(55%, 1400px);
  }
  .chat-message {
    font-size: 16px;
  }
  .adaptive-chat-img {
    max-height: 140px;
  }
    .custom-textarea :deep(.el-textarea__inner) {

  min-height: 140px!important; 
  max-height: 260px !important;
}
}

/* 2. 大屏幕显示器 (1751px - 1919px) */
@media (min-width: 1751px) and (max-width: 1919px) {
  .fixed-bottom{ margin: 0 auto 9vh; }

  /* 聊天相关 */
  .chat-messages,
  .fixed-bottom,
  .control-bar {
    width: min(55%, 1400px); 
  }
  .chat-message {
    font-size: 16px;
  }
  .adaptive-chat-img {
    max-height: 140px;
  }
    .custom-textarea :deep(.el-textarea__inner) {

  min-height: 130px!important; 
  max-height: 250px !important;
}
}

/* 3. 中大屏幕显示器 (1601px - 1750px) */
@media (min-width: 1601px) and (max-width: 1750px) {

 .fixed-bottom{ margin: 0 auto 10vh; }
  /* 聊天相关 */
  .chat-messages,
  .fixed-bottom,
  .control-bar {
    width: min(55%, 1400px); 
  }
  .chat-message {
    font-size: 16px;
  }
  .adaptive-chat-img {
    max-height: 140px;
  }
  .custom-textarea :deep(.el-textarea__inner) {

  min-height: 120px!important; 
  max-height: 240px !important;
}
}

/* 4. 标准桌面显示器 (≤1600px) */
@media (max-width: 1600px) {


  /* 聊天相关 */
  .chat-messages,
  .fixed-bottom,
  .control-bar {
    width: min(55%, 1400px); 
  }
  .chat-message {
    font-size: 16px;
  }
  .adaptive-chat-img {
    max-height: 140px;
  }
}

/* 5. 小尺寸桌面显示器 (≤1440px) */
@media (max-width: 1440px) {
 .fixed-bottom{ margin: 0 auto 12vh; }

  /* 聊天相关 */
  .chat-messages,
  .fixed-bottom,
  .control-bar {
    width: 65%; 
  }
  .chat-message {
    font-size: 16px; 
  }
  .adaptive-chat-img {
    max-height: 140px; 
  }
  .custom-textarea :deep(.el-textarea__inner) {
  min-height: 60px!important; 
  max-height: 140px !important;
}
}

/* 6. 笔记本屏幕 (≤1280px) */
@media (max-width: 1280px) {

 .fixed-bottom{ margin: 0 auto 13vh; }
  /* 聊天相关 */
  .chat-messages,
  .fixed-bottom,
  .control-bar {
    width: 75%; 
  }
  .chat-message {
    font-size: 16px; 
  }
  .adaptive-chat-img {
    max-height: 140px; 
  }
.custom-textarea :deep(.el-textarea__inner) {
  min-height: 50px!important; 
  max-height: 130px !important;
}

}

/* 7. 平板横屏和小笔记本 (≤992px) */
@media (max-width: 992px) {


  /* 聊天相关 */
  .chat-messages,
  .fixed-bottom,
  .control-bar {
    width: 85%; 
  }
  .chat-message {
    font-size: 16px; 
  }
  .adaptive-chat-img {
    max-height: 140px; 
  }
  .file-item {
    width: 100%; 
  }
}

</style>
